package com.youpai.platform.chat.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youpai.platform.chat.service.converter.ChatMessageConverter;
import com.youpai.platform.chat.service.entity.dto.ChatMessageDTO;
import com.youpai.platform.chat.service.entity.dto.ChatSessionDTO;
import com.youpai.platform.chat.service.entity.po.ChatAccountPO;
import com.youpai.platform.chat.service.entity.po.ChatMessagePO;
import com.youpai.platform.chat.service.entity.po.ChatSessionPO;
import com.youpai.platform.chat.service.mapper.ChatAccountMapper;
import com.youpai.platform.chat.service.mapper.ChatMessageMapper;
import com.youpai.platform.chat.service.mapper.ChatSessionMapper;
import com.youpai.platform.chat.service.service.ChatSessionService;
import com.youpai.platform.chat.service.util.ChatUtils;
import com.youpai.platform.common.util.StringUtils;
import com.youpai.platform.user.service.biz.UserActiveBizService;
import com.youpai.platform.user.service.entity.dto.UserActiveDTO;
import com.youpai.platform.vulture.service.router.MessageRouterService;
import com.youpai.platform.chat.web.entity.req.SyncSessionListRequest;
import com.youpai.platform.common.enums.ProcessCodeEnum;
import com.youpai.platform.common.exceptions.BaseBizException;
import com.youpai.platform.common.util.UserContext;
import com.youpai.platform.user.service.entity.po.UserPO;
import com.youpai.platform.user.service.mapper.UserMapper;
import com.youpai.platform.user.web.entity.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @date: 2022/7/17 15:05
 * @author: Anna
 * @version: 1.0
 * @description: 会话service
 */
@Slf4j
@Component
public class ChatSessionServiceImpl implements ChatSessionService {

    @Resource
    private MessageRouterService messageRouterService;
    @Resource
    private ChatSessionMapper chatSessionMapper;
    @Resource
    private ChatAccountMapper chatAccountMapper;
    @Resource
    private ChatMessageMapper chatMessageMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserActiveBizService userActiveBizService;

    private static final Integer pageSize = 10;

    @Override
    public List<ChatSessionDTO> syncSessionListRequest(SyncSessionListRequest req) {
        // 异步执行
        String accId = getAccId();
        List<ChatSessionDTO> chatSessionList = queryChatSessionList(accId, req.getFromTimeStamp());
        if (CollectionUtils.isEmpty(chatSessionList)) {
            return Collections.emptyList();
        }
        return chatSessionList;
    }

    private List<ChatSessionDTO> queryChatSessionList(String accId, String fromTimeStamp) {
        // TODO NPE  -> huanghao
        Date fromDate = new Date(StringUtils.parseLong(fromTimeStamp));
        LambdaQueryWrapper<ChatSessionPO> queryWrapper = new LambdaQueryWrapper<ChatSessionPO>()
                .eq(ChatSessionPO::getAccId, accId)
                .ge(ChatSessionPO::getUpdateTime, fromDate)
                .orderByDesc(ChatSessionPO::getUpdateTime)
                .last("limit 10");
        List<ChatSessionPO> chatSessionPOList = chatSessionMapper.selectList(queryWrapper);
        return convertChatSessionPOList2ChatSessionDTOList(chatSessionPOList);
    }

    private List<ChatSessionDTO> convertChatSessionPOList2ChatSessionDTOList(List<ChatSessionPO> chatSessionPOList) {
        if (CollectionUtils.isEmpty(chatSessionPOList)) {
            return Collections.emptyList();
        }
        // 构建服务端会话id列表
        List<String> sessionIdList = chatSessionPOList.stream().map(ChatSessionPO::getSessionId).collect(Collectors.toList());
        Map<String, LinkedList<ChatMessagePO>> chatMessagePOMap = buildMsgMap(sessionIdList);
        List<String> accIdList = new LinkedList<>();
        chatSessionPOList.forEach(
                chatSessionPO -> accIdList.add(ChatUtils.getAnotherAccId(chatSessionPO.getSessionId(), chatSessionPO.getAccId()))
        );
        // 获取chatAccount信息
        List<ChatAccountPO> chatAccountPOList = queryChatAccountList(accIdList);
        // 构建uid到accId的映射关系
        Map<String, String> uid2AccIdMap = chatAccountPOList.stream().collect(Collectors.toMap(ChatAccountPO::getUid, ChatAccountPO::getAccId));
        // 获取用户信息Map
        Map<String, UserPO> userMap = queryUserMap(chatAccountPOList, uid2AccIdMap);
        // 获取用户active信息Map
        Map<String, UserActiveDTO> userActiveMap = queryUserActiveMap(chatAccountPOList, uid2AccIdMap);
        List<ChatSessionDTO> resultList = new ArrayList<>(chatSessionPOList.size());
        for (ChatSessionPO chatSessionPO : chatSessionPOList) {
            ChatSessionDTO chatSessionDTO = buildChatSessionDTO(chatSessionPO, chatMessagePOMap, userMap, userActiveMap);
            resultList.add(chatSessionDTO);
        }
        return resultList;
    }

    private List<ChatAccountPO> queryChatAccountList(List<String> accIdList) {
        // 查询account详情列表
        LambdaQueryWrapper<ChatAccountPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ChatAccountPO::getAccId, accIdList);
        return chatAccountMapper.selectList(queryWrapper);
    }

    private Map<String, UserActiveDTO> queryUserActiveMap(List<ChatAccountPO> chatAccountPOList, Map<String, String> uid2AccIdMap) {
        // 构建uid列表
        List<Long> uidList = new ArrayList<>(chatAccountPOList.size());
        chatAccountPOList.forEach(chatAccountPO -> uidList.add(Long.valueOf(chatAccountPO.getUid())));
        Map<Long, UserActiveDTO> userActiveDTOMap = userActiveBizService.queryUserActive(uidList);
        Map<String, UserActiveDTO> resultMap = new HashMap<>(chatAccountPOList.size());
        userActiveDTOMap.forEach((key, value) -> resultMap.put(uid2AccIdMap.get(key.toString()), value));
        return resultMap;
    }

    private Map<String, UserPO> queryUserMap(List<ChatAccountPO> chatAccountPOList, Map<String, String> uid2AccIdMap) {
        // 构建uid列表
        List<Long> uidList = new ArrayList<>(chatAccountPOList.size());
        chatAccountPOList.forEach(chatAccountPO -> uidList.add(Long.valueOf(chatAccountPO.getUid())));
        // 获取用户信息列表
        List<UserPO> userList = queryUserList(uidList);
        Map<String, UserPO> resultMap = new HashMap<>(chatAccountPOList.size());
        userList.forEach(user -> resultMap.put(uid2AccIdMap.get(user.getUid().toString()), user));
        return resultMap;
    }

    private List<UserPO> queryUserList(List<Long> uidList) {
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(UserPO::getUid, uidList);
        return userMapper.selectList(queryWrapper);
    }

    private ChatSessionDTO buildChatSessionDTO(ChatSessionPO chatSessionPO, Map<String, LinkedList<ChatMessagePO>> chatMessagePOMap, Map<String, UserPO> userMap, Map<String, UserActiveDTO> userActiveMap) {
        LinkedList<ChatMessagePO> chatMessagePOList = chatMessagePOMap.get(chatSessionPO.getSessionId());
        UserPO user = userMap.get(ChatUtils.getAnotherAccId(chatSessionPO.getSessionId(), chatSessionPO.getAccId()));
        UserActiveDTO userActive = userActiveMap.get(ChatUtils.getAnotherAccId(chatSessionPO.getSessionId(), chatSessionPO.getAccId()));
        ChatSessionDTO chatSessionDTO = new ChatSessionDTO();
        chatSessionDTO.setSessionId(chatSessionPO.getSessionId());
        chatSessionDTO.setToUid(ChatUtils.getUidByAccId(ChatUtils.getAnotherAccId(chatSessionPO.getSessionId(), chatSessionPO.getAccId())));
        chatSessionDTO.setLastMsgId(chatSessionPO.getLastMsgId());
        chatSessionDTO.setLastModifyTimeStamp(chatSessionPO.getUpdateTime().getTime());
        if (null != user) {
            chatSessionDTO.setAvatar(user.getAvatar())
                    .setNickName(user.getNickName());
        }
        if (null != userActive) {
            chatSessionDTO.setUserStateTag(userActive.getUserStateTag())
                    .setUserState((userActive.getUserState() > 1) ? 1 : userActive.getUserState());
        }
        if (CollectionUtils.isNotEmpty(chatMessagePOList)) {
            LinkedList<ChatMessageDTO> chatMessageList = ChatMessageConverter.convertChatMessagePOList2ChatMessageDTOList(chatMessagePOList);
            if (chatMessageList.size() > pageSize) {
                chatMessageList.removeFirst();
            }
            chatSessionDTO.setLastMsgType(chatMessageList.getLast().getMsgType())
                    .setPreMsg(chatMessagePOList.getLast().getContent());
        }
        return chatSessionDTO;
    }

    private Map<String, LinkedList<ChatMessagePO>> buildMsgMap(List<String> sessionIdList) {
        Map<String, LinkedList<ChatMessagePO>> resultMap = new HashMap<>(1);
        for (String sessionId : sessionIdList) {
            LambdaQueryWrapper<ChatMessagePO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ChatMessagePO::getSessionId, sessionId)
                    .orderByDesc(ChatMessagePO::getMessageId)
                    .last("limit 1");
            List<ChatMessagePO> chatMessagePOList = chatMessageMapper.selectList(queryWrapper);
            LinkedList<ChatMessagePO> sublist = new LinkedList<>(chatMessagePOList);
            resultMap.put(sessionId, sublist);
        }
        return resultMap;
    }

    private String getAccId() {
        UserDTO userContext = UserContext.getUserContext();
        String uid = userContext.getUid();
        ChatAccountPO chatAccountPO = chatAccountMapper.selectOne(new LambdaQueryWrapper<ChatAccountPO>().eq(ChatAccountPO::getUid, uid));
        if (null == chatAccountPO) {
            log.error("accId 没有注册 ， uid {}", uid);
            throw new BaseBizException(ProcessCodeEnum.CHAT_ACCOUNT_NOT_FOUND);
        }
        return chatAccountPO.getAccId();
    }
}
